using System;
using System.Xml;
using Castle.Core.Resource;

namespace Mbs.CastleContainer
{
    class IncludeElementProcessor : AbstractXmlNodeProcessor
    {
        public IncludeElementProcessor()
        {
        }

        public override String Name
        {
            get { return "include"; }
        }


        public override bool Accept(XmlNode node)
        {
            return node.Attributes.GetNamedItem("uri") != null && base.Accept(node);
        }

        public override void Process(IXmlProcessorNodeList nodeList, IXmlProcessorEngine engine)
        {
            XmlElement element = nodeList.Current as XmlElement;

            XmlNode result = ProcessInclude(element, element.GetAttribute("uri"), engine);

            ReplaceItself(result, element);
        }

        public XmlNode ProcessInclude(XmlElement element, String includeUri, IXmlProcessorEngine engine)
        {
            XmlDocumentFragment frag = null;

            if (includeUri == null)
            {
                throw new ConfigurationProcessingException(
                    String.Format("Found an include element without an 'uri' attribute: {0}", element.BaseURI));
            }

            String[] uriList = includeUri.Split(',');
            frag = CreateFragment(element);

            foreach (String uri in uriList)
            {
                using (IResource resource = engine.GetResource(uri))
                {
                    XmlDocument doc = new XmlDocument();

                    try
                    {
                        doc.Load(resource.GetStreamReader());
                    }
                    catch (Exception ex)
                    {
                        throw new ConfigurationProcessingException(
                            String.Format("Error processing include element: {0}", includeUri), ex);
                    }

                    engine.PushResource(resource);

                    engine.DispatchProcessAll(new DefaultXmlProcessorNodeList(doc.DocumentElement));

                    engine.PopResource();

                    if (element.GetAttribute("preserve-wrapper") == "yes")
                    {
                        AppendChild(frag, doc.DocumentElement);
                    }
                    else
                    {
                        AppendChild(frag, doc.DocumentElement.ChildNodes);
                    }
                }
            }

            return frag;
        }
    }
}
